package org.yang.parser.types;

import com.sun.istack.internal.NotNull;
import org.yang.parser.Analyzer;

import java.util.ArrayList;
import java.util.List;

public class ListType extends Type {

    public Type eltType;
    @NotNull
    public List<Type> positional = new ArrayList<>();
    @NotNull
    public List<Object> values = new ArrayList<>();

    public ListType(){
        this(Types.UNKNOW);
    }

    public ListType(Type elt0){
        eltType = elt0;
        table.addSuper(Analyzer.self.builtins.BaseList.table);
        table.setPath(Analyzer.self.builtins.BaseList.table.path);
    }

    public void setElementType(Type eleType){
        this.eltType = eltType;
    }

    public void add(@NotNull Type another){
        eltType = UnionType.union(eltType, another);
        positional.add(another);
    }

    public void addValue(Object v){
        values.add(v);
    }

    public Type get(int i){
        return positional.get(i);
    }

    @NotNull
    public TupleType toTupleType(int n){
        TupleType ret = new TupleType();
        for(int i=0; i<n; i++){
            ret.add(eltType);
        }
        return ret;
    }

    @NotNull
    public TupleType toTupleType(){
        return new TupleType(positional);
    }

    @Override
    public boolean typeEquals(Object other) {
        if(typeStack.contains(this, other)){
            return true;
        } else if(other instanceof ListType){
            ListType co = (ListType) other;
            typeStack.push(this, other);
            boolean result = co.eltType.typeEquals(eltType);
            typeStack.pop(this, other);
            return result;
        } else {
            return false;
        }
    }

    @Override
    public int hashCode(){
        return "ListType".hashCode();
    }

    @Override
    protected String printType(CyclicTypeRecorder ctr) {
        StringBuilder sb = new StringBuilder();

        Integer num = ctr.visit(this);
        if(null != num){
            sb.append("#").append(num);
        } else {
            ctr.push(this);
            sb.append("[");
            sb.append(eltType.printType(ctr));
            sb.append("]");
            ctr.pop(this);
        }

        return sb.toString();
    }
}
